#include "PlayOnWithoutBallBehaviour.h"

extern CEvaluatingPlayerList* ePlayerList;

//konstruktor, nastavia sa domovske pozicie hracov
PlayOnWithoutBallBehaviour::PlayOnWithoutBallBehaviour()
{
	homePositions[0] = Point(-45,   0);		// Hrac c.1
	homePositions[1] = Point(-34,   0);		// Hrac c.2
	homePositions[2] = Point(-34,  -8.5);	// Hrac c.3
	homePositions[3] = Point(-34,   8.5);	// Hrac c.4
	homePositions[4] = Point(-15,   0.0);	// Hrac c.5
	homePositions[5] = Point(-15, -19);		// Hrac c.6
	homePositions[6] = Point(-15,  19);		// Hrac c.7
	homePositions[7] = Point(-2,   22);		// Hrac c.8
	homePositions[8] = Point(-2,  -22);		// Hrac c.9
	homePositions[9] = Point(-4,    8);		// Hrac c.10
	homePositions[10]= Point(-4,   -8);		// Hrac c.11
}

/*
 * Spravanie hraca bez lopty pocas normalnej hry, ak nie je prerusena.
 *
 * @return vracia true ak sa vykonala nejaka cinnost, inak false
 */
bool PlayOnWithoutBallBehaviour::Behave()
{
	if(DATA_STORAGE.InOffsidePos())
	{
		// Je v ofsajde
		GetRunToPositionBehaviour()->ExitOffside();
		return true;
	}
	else if (DATA_STORAGE.ballPosition.GetX() < -20.0 && DATA_STORAGE.ballPosition.GetX() > -35.0)
	{
		// obranca sa postavi k tycke => buuuuug treba upravit runtopoint tak aby neostal ten fas stat na mieste
		if (DATA_STORAGE.ballPosition.GetY() > 0.0)
		{
			if (DATA_STORAGE.myUniform == 3)
			{
				//povodny bol Point(-34,  -8.5);
				homePositions[DATA_STORAGE.myUniform - 1] = Point(-45.0,-4.5);
				if (!DATA_STORAGE.DependentForBall()) 
				{
					GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
					return true;
				}
			}	
		}
		else
		{
			if (DATA_STORAGE.myUniform == 4)
			{
				// povodny bol Point(-34,   8.5);
				homePositions[DATA_STORAGE.myUniform - 1] = Point(-45.0,4.5);
				if (!DATA_STORAGE.DependentForBall()) 
				{
					//RunToPoint(homePositions[DATA_STORAGE.myUniform -1], true, true);
					GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
					return true;
				}
			}
		}

		switch(DATA_STORAGE.myUniform)
		{
		/*homePositions[4] = Point(-15,   0.0);	// Hrac c.5
		homePositions[5] = Point(-15, -19);		// Hrac c.6
			homePositions[6] = Point(-15,  19);		// Hrac c.7*/
		case 5:
			homePositions[DATA_STORAGE.myUniform - 1] = Point(-30.0,0.0);
			if (!DATA_STORAGE.DependentForBall()) 
			{
				//RunToPoint(homePositions[DATA_STORAGE.myUniform -1], true, true);
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
				return true;
			}
			break;
		case 6:
			homePositions[DATA_STORAGE.myUniform -1] = Point(-30.0, -19.0);
			if (!DATA_STORAGE.DependentForBall())
			{
				
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
				return true;
			}
			break;
		case 7:
			homePositions[DATA_STORAGE.myUniform-1] = Point(-30.0, 19.0);
			if (!DATA_STORAGE.DependentForBall())
			{
				
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform-1], 2);
				return true;
			}
			break;
		default:
			break;
		}
	}
	else if (DATA_STORAGE.ballPosition.GetX() > -20.0) 
	{
		// zmena home position nas5 na povodne hodnoty
		/*	
		if (myUniform == 3)
		{
		//povodny bol Point(-34,  -8.5);
		homePositions[myUniform - 1] = Point(-34,  -8.5);
		//RunToPoint(homePositions[myUniform -1], true, true);
		GetRunToPositionBehaviour()->Behave(homePositions[myUniform -1], 2);
		return;
		
		  }
		  else if (myUniform == 4) 
		  {	// povodny bol Point(-34,   8.5);
		  homePositions[myUniform - 1] = Point(-34,   8.5);
		  //RunToPoint(homePositions[myUniform -1], true, true);
		  GetRunToPositionBehaviour()->Behave(homePositions[myUniform -1], 2);
		  return;
		  
			}
		*/
		
		if (DATA_STORAGE.ballPosition.GetY() > 0.0)
		{
			if (DATA_STORAGE.myUniform == 3)
			{
				//povodny bol Point(-34,  -8.5);
				homePositions[DATA_STORAGE.myUniform - 1] = Point(-34,  -8.5);
				if (!DATA_STORAGE.DependentForBall()) 
				{
					GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
					return true;
				}
			}	
		}
		else
		{
			if (DATA_STORAGE.myUniform == 4)
			{
				// povodny bol Point(-34,   8.5);
				homePositions[DATA_STORAGE.myUniform - 1] = Point(-34,   8.5);
				if (!DATA_STORAGE.DependentForBall()) 
				{
					//RunToPoint(homePositions[DATA_STORAGE.myUniform -1], true, true);
					GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
					return true;
				}
			}
		}

		switch(DATA_STORAGE.myUniform)
		{	
		/*homePositions[4] = Point(-15,   0.0);	// Hrac c.5
		homePositions[5] = Point(-15, -19);		// Hrac c.6
			homePositions[6] = Point(-15,  19);		// Hrac c.7*/
		case 5:
			homePositions[DATA_STORAGE.myUniform - 1] = Point(-15.0,0.0);
			if (!DATA_STORAGE.DependentForBall()) 
			{
				//RunToPoint(homePositions[DATA_STORAGE.myUniform -1], true, true);
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
				return true;
			}
			break;
		case 6:
			homePositions[DATA_STORAGE.myUniform -1] = Point(-15.0, -19.0);
			if (!DATA_STORAGE.DependentForBall())
			{
				
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform -1], 2);
				return true;
			}
			break;
		case 7:
			homePositions[DATA_STORAGE.myUniform-1] = Point(-15.0, 19.0);
			if (!DATA_STORAGE.DependentForBall())
			{
				
				GetRunToPositionBehaviour()->Behave(homePositions[DATA_STORAGE.myUniform-1], 2);
				return true;
			}
			break;
		default:
			break;
		}
	}
	
	// Zvysni hraci pri zahravani ostavaju na mieste
	if(DATA_STORAGE.ShouldKickIn())
	{
		DATA_STORAGE.formation.SetSide( SIDE_LEFT );
		Point pos = DATA_STORAGE.formation.GetPlayerPosition( world->me->GetUniform(), DATA_STORAGE.ballPosition);
		GetRunToPositionBehaviour()->Behave(pos, 1);
		return true;
	}

	// Ked som natoceny na branku a moze padnut gol smykackou
	float posX = world->params->flags[GOAL_R].GetX();
	
	Point tGoal(posX, -(world->params->server->goal_width / 2) * .9f);
	Point bGoal(posX, (world->params->server->goal_width / 2) * .9f);
	
	Vector tVect = tGoal - DATA_STORAGE.myPosition;
	Vector bVect = bGoal - DATA_STORAGE.myPosition;

	Player* enemyGoalie = DATA_STORAGE.GetEnemyGoalie();

	if(GetTackleBehaviour()->CanTackleBall()&& world->me->GetAbsDir().GetDeg() >= tVect.GetAngle().GetDeg() && 
	   world->me->GetAbsDir().GetDeg() <= bVect.GetAngle().GetDeg() && 
	   (GetKickToGoalBehaviour()->ShouldKickOnGoal() || (enemyGoalie != NULL && (enemyGoalie->pos - DATA_STORAGE.ballPosition).GetLength() < 4.f)))
	{
		//TXTN("%d: I am tackling", world->state->GetSimTime());
		GetTackleBehaviour()->Behave(100.0f);
		return true;
	}

	bool bInterceptBall = false;

	if(!DATA_STORAGE.ignoreBall)
		bInterceptBall = GetInterceptBallBehaviour()->Behave();//InterceptBall();
	
	if(!bInterceptBall)
	{				
		const float off_l = DATA_STORAGE.GetOffsideLine();

		if(DATA_STORAGE.InOffsidePos())
		{
			// Je v ofsajde
			GetRunToPositionBehaviour()->ExitOffside();
			return true;
		}
		else
		{
			DATA_STORAGE.formation.SetSide( SIDE_LEFT );

			Point pos = DATA_STORAGE.formation.GetPlayerPosition( world->me->GetUniform(), DATA_STORAGE.ballPosition);
			double lfNewPosX = pos.GetX();
			double lfNewPosY = pos.GetY();
					
			// Kazdych 100 cyklov sa pocas 10 cyklov vracaju hraci spat do formacie.
 			if(world->state->GetSimTime() % 100 < 20)
			{
				pos = DATA_STORAGE.formation.GetPlayerPosition( world->me->GetUniform(), DATA_STORAGE.ballPosition);
			}
			// Hraci, ktori su mimo 
			else if(fabs((DATA_STORAGE.myPosition - DATA_STORAGE.ballPosition).GetLength()) > lfMaxPassDistance)
			{
				GetTurnToBehaviour()->Behave(DATA_STORAGE.ballPosition + world->ball->vel);
				GetAlignNeckBehaviour()->Behave();
				return true;
			}
			else if(ePlayerList->CalculateReceiveBallPositionAux(lfNewPosX, lfNewPosY, DATA_STORAGE.ballPosition.GetX(), DATA_STORAGE.ballPosition.GetY()))
			{
				pos.SetX((float)lfNewPosX);
				pos.SetY((float)lfNewPosY);
			}

			// Rozostavenie utocnikov do formacie dazdnik (Umbrella formation)
			if((DATA_STORAGE.myUniform == 8) || (DATA_STORAGE.myUniform == 9) || (DATA_STORAGE.myUniform == 10) || (DATA_STORAGE.myUniform == 11))
			{
				float fTmpDistance = DATA_STORAGE.umbrellaPositions[DATA_STORAGE.myUniform - 8].GetX() - DATA_STORAGE.ballPosition.GetX();
				// TODO: Pridat sem podmienku "Ked utocime"
 				if(/* WeDoAttack()  && */ (fTmpDistance > 8) && (fTmpDistance < 20)) // && (umbrellaPositions[DATA_STORAGE.myUniform - 8] - pos).GetLength() < 10.0f)
				{
					pos.SetX(DATA_STORAGE.umbrellaPositions[DATA_STORAGE.myUniform - 8].GetX());
					pos.SetY(DATA_STORAGE.umbrellaPositions[DATA_STORAGE.myUniform - 8].GetY());
				}
			}
					
			Vector dist = pos - DATA_STORAGE.myPosition;

			if(dist.GetLength() > 2.0)
			{
				// Test na ofsajd
				if(pos.GetX() > off_l - 0.1f)
					pos.SetX(off_l - 1.0f);
				// Pobehni na svoju poziciu
				GetRunToPositionBehaviour()->Behave(pos, 1);
				return true;
			}
			else
			{
				// Ak som blokovany superom, pobehni trochu blizsie k lopte
				Vector shift;
				if(GetUnblockMyselfBehaviour()->Behave(&shift))
				{
					Point tmp = DATA_STORAGE.myPosition + shift;
					//UBLK_DBGN("%i: Unblocking by (%3.2f, %3.2f) - from (%3.2f, %3.2f) to (%3.2f, %3.2f)", world->state->GetSimTime(), shift.GetX(), shift.GetY(), world->me->pos.GetX(), world->me->pos.GetY(), tmp.GetX(), tmp.GetY());

					// test offside
					if(tmp.GetX() > off_l - 0.1f)
						tmp.SetX(off_l - 1.0f);
					// pobehni na svoju poziciu
					GetRunToPositionBehaviour()->Behave(tmp, 2);
					return true;
				}
				else
				{
					int t = world->me->GetSeeCount() % 3;

					// pozeraj sa na vsetky strany
					if(t != 0)
					{
						GetTurnToBehaviour()->Behave(DATA_STORAGE.ballPosition);
						GetAlignNeckBehaviour()->Behave();
						return true;
					}
					else
					{
						Point tmp = DATA_STORAGE.ballPosition;
						tmp.SetY(-DATA_STORAGE.ballPosition.GetY());

						GetTurnNeckToBehaviour()->Behave(tmp, DATA_STORAGE.myPosition);
						return true;
					}
				}
			}
		}
	}
	return false;
}